﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using DynaPrecision.LinearSystem;

namespace DynaPrecision.Numerical.Poisson
{
	public class PoissonMatrixProcessor<TMesh, TSource, T> : ILinearSystemGenerator<T>
		where TMesh : Mesh.ICartesianMeshData<T>
		where TSource : IMultiDimensionalArray<T>
	{

		public TMesh Mesh { get; set; }
		public TSource Source { get; set; }

		#region ILinearSystemGenerator<T> Members

		public void ProcessLeftMatrix<TLeftArray>(ref TLeftArray leftMatrixStorage) where TLeftArray : IMultiDimensionalArray<T>
		{
			int length0 = Mesh.GetLength(0);
			int length1 = Mesh.GetLength(1);
			for (int i = 1; i < length0 - 1; i++)
			{
				for (int j = 1; j < length1 - 1; j++)
				{
					int currentI = j * length0 + i;
					leftMatrixStorage[currentI, currentI] = -2.0 / (dynamic)Mesh.Difference(0, i - 1, j) / Mesh.Difference(0, i, j) - 2.0 / (dynamic)Mesh.Difference(1, i, j - 1) / Mesh.Difference(1, i, j);
					leftMatrixStorage[currentI, currentI - 1] = 2.0 / (dynamic)Mesh.Difference(0, i - 1, j) / ((dynamic)Mesh.Difference(0, i - 1, j) + Mesh.Difference(0, i, j));
					leftMatrixStorage[currentI, currentI + 1] = 2.0 / (dynamic)Mesh.Difference(0, i, j) / ((dynamic)Mesh.Difference(0, i - 1, j) + Mesh.Difference(0, i, j));
					leftMatrixStorage[currentI, currentI - length0] = 2.0 / (dynamic)Mesh.Difference(1, i, j - 1) / ((dynamic)Mesh.Difference(1, i, j - 1) + Mesh.Difference(1, i, j));
					leftMatrixStorage[currentI, currentI + length0] = 2.0 / (dynamic)Mesh.Difference(1, i, j) / ((dynamic)Mesh.Difference(1, i, j - 1) + Mesh.Difference(1, i, j));
				}
			}
		}

		public void ProcessRightMatrix<TRightArray>(ref TRightArray rightMatrix) where TRightArray : IMultiDimensionalArray<T>
		{
			int length0 = Mesh.GetLength(0);
			int length1 = Mesh.GetLength(1);
			for (int i = 1; i < length0 - 1; i++)
			{
				for (int j = 1; j < length1 - 1; j++)
				{
					int currentI = j * length0 + i;
					rightMatrix[currentI, 0] = Source[i, j];
				}
			}
		}

		#endregion
	}
}
